import 'package:flutter/material.dart';

extension StringEx on String {
  /// 解决系统默认换行从中文与（英文或数字）处截断问题，加了此处理后，
  /// 只会在单行显示不下的字符处换行，不会提前换行
  String fixSoftWrap() {
    var data = this;
    if (data.length < 2) {
      return data;
    }

    if (data.length > 100) {
      // 超过100个字符不处理，防止影响性能，一般使用此方法都是展示标签，不会在输入框使用，因此字符长度不会太长
      return data;
    }

    String strs = '';
    int offset = 0;
    while (offset < data.length) {
      if (offset < data.length - 1) {
        var str = data.substring(offset, offset + 2);
        if (str.isEmoji) {
          offset += 2;
          strs += '$str\u200b';
        } else {
          strs += '${data.substring(offset, offset + 1)}\u200b';
          offset++;
        }
      } else {
        strs += '${data.substring(offset, offset + 1)}\u200b';
        offset++;
      }
    }

    return strs;
  }

  /// 将两个字符串拼接在一起
  ///
  /// [delimiter]为字符之间的分隔符，
  ///
  /// [emptyAppend]表示字符为空串或null时是否参与拼接
  ///
  /// [allUnEmptyAppend]表示拼接的字符串全部不为null或空串时才拼接，否则只要任何一个字符为null或空串，都返回空串。
  ///
  /// [appendHead]表示将给定字符[str]拼接在当前字符前面
  String append(
    String? str, {
    String delimiter = "",
    bool emptyAppend = false,
    bool allUnEmptyAppend = false,
    bool appendHead = false,
  }) {
    if (allUnEmptyAppend) {
      if (isEmpty || str == null || str.isEmpty) {
        return '';
      }
    }

    if (isEmpty && !emptyAppend) {
      return str ?? '';
    }

    if ((str == null || str.isEmpty) && !emptyAppend) {
      return this;
    }

    return appendHead
        ? '${str ?? ''}$delimiter$this'
        : '$this$delimiter${str ?? ''}';
  }
}

extension StringNullEx on String? {
  bool get isNullOrEmpty => this == null || this!.isEmpty;

  bool get isNotNullOrEmpty => this != null && this!.isNotEmpty;

  /// 比较两个字符串是否相等，如果都为null或空串，通过[emptySame]来决定是否相等。
  /// 如果需要相等则[emptySame]置为true即可，默认false
  bool equal(String? other, [bool emptySame = false]) {
    if (isNullOrEmpty && other.isNullOrEmpty) {
      return emptySame;
    }

    if (isNotNullOrEmpty && other.isNotNullOrEmpty) {
      return this == other;
    }

    // this 和 other 中至少有一个是null或空串，而另外一个是有值的，因此始终不相等
    return false;
  }

  /// 解决系统默认换行从中文与（英文或数字）处截断问题，加了此处理后，
  /// 只会在单行显示不下的字符处换行，不会提前换行
  String? fixSoftWrap() {
    return this?.fixSoftWrap();
  }

  /// 是否是表情符号
  bool get isEmoji {
    var str = this;
    if (str == null || str.length != 2) {
      return false;
    }

    return _isEmojiCharacter(str.codeUnitAt(0)) &&
        _isEmojiCharacter(str.codeUnitAt(1));
  }

  static bool _isEmojiCharacter(int codePoint) {
    return !((codePoint == 0x0) ||
        (codePoint == 0x9) ||
        (codePoint == 0xA) ||
        (codePoint == 0xD) ||
        ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) ||
        ((codePoint >= 0xE000) && (codePoint <= 0xFFFD)));
  }

  /// 将两个字符串拼接在一起
  ///
  /// [delimiter]为字符之间的分隔符，
  ///
  /// [emptyAppend]表示字符为空串或null时是否参与拼接
  ///
  /// [allUnEmptyAppend]表示拼接的字符串全部不为null或空串时才拼接，否则只要任何一个字符为null或空串，都返回null。
  ///
  /// [appendHead]表示将给定字符[str]拼接在当前字符前面
  String? append(
    String? str, {
    String delimiter = "",
    bool emptyAppend = false,
    bool allUnEmptyAppend = false,
    bool appendHead = false,
  }) {
    if (allUnEmptyAppend) {
      if (isNullOrEmpty || str.isNullOrEmpty) {
        return null;
      }
    }

    if ((this == null || this!.isEmpty) && !emptyAppend) {
      return str;
    }

    if ((str == null || str.isEmpty) && !emptyAppend) {
      return this;
    }

    return appendHead
        ? '${str ?? ''}$delimiter${this ?? ''}'
        : '${this ?? ''}$delimiter${str ?? ''}';
  }

  /// 为空则返回占位符,占位符默认'-',可自定义。
  String placeHolder([String placeHolderString = "-"]) {
    return isNullOrEmpty ? placeHolderString : this!;
  }

  /// 将字符类型颜色值转化为[Color]
  Color hexToColor({Color defaultColor = Colors.white}) {
    return hexToColorOrNull() ?? defaultColor;
  }

  /// 将字符类型颜色值转化为[Color]
  Color? hexToColorOrNull() {
    var hexString = this;
    if (hexString == null || hexString.isEmpty) {
      return null;
    }

    if (!hexString.startsWith('#')) {
      return null;
    }

    hexString = hexString.substring(1);
    var length = hexString.length;
    if (length != 3 && length != 4 && length != 6 && length != 8) {
      return null;
    }

    if (hexString.length == 3) {
      hexString =
          'FF${hexString[0]}${hexString[0]}${hexString[1]}${hexString[1]}${hexString[2]}${hexString[2]}';
    } else if (hexString.length == 4) {
      hexString =
          '${hexString[0]}${hexString[0]}${hexString[1]}${hexString[1]}${hexString[2]}${hexString[2]}${hexString[3]}${hexString[3]}';
    } else if (hexString.length == 6) {
      hexString = 'FF$hexString';
    }

    var value = int.tryParse(hexString, radix: 16);
    if (value == null) {
      return null;
    }

    return Color(value);
  }

  int? toInt() {
    if (this?.isNotEmpty != true) {
      return null;
    }

    return int.tryParse(this!);
  }

  double? toDouble() {
    if (this?.isNotEmpty != true) {
      return null;
    }

    return double.tryParse(this!);
  }
}
